#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string>
#include <iostream>

/*
这些函数属于 POSIX 共享内存 API，定义在 librt 库中。在编译和链接时，需要显式地链接 librt 库。
target_link_libraries(${TagetName} rt)
*/


int CreateSharedMemory(int *fd , std::string shared_mem_name)
{
     // 创建并打开共享内存对象
    *fd = shm_open(shared_mem_name.c_str(), O_CREAT | O_RDWR | O_EXCL, 0666);
    // O_RDONLY: 以只读方式打开共享内存对象。
    // O_RDWR: 以读写方式打开共享内存对象。
    // O_CREAT: 如果共享内存对象不存在，则创建它。
    // O_EXCL: 如果指定了 O_CREAT 并且共享内存对象已经存在，则返回错误。
    // O_TRUNC: 如果共享内存对象已经存在，并且以可写方式打开，则将其长度截断为0
    // 0666: 共享内存对象的权限（八进制），表示所有用户可读写。
    if(*fd == -1)
    {
        if(errno == EEXIST)
        {
            shm_unlink(shared_mem_name.c_str());
        }
        perror("shm_open");
        exit(EXIT_FAILURE);
    }
    return 0;
}

int SetSharedMemoryObjectSize(int fd , size_t mem_size,  std::string shared_mem_name)
{
    // 设置共享内存对象的大小
    if (ftruncate(fd, mem_size) == -1) {
        shm_unlink(shared_mem_name.c_str());
        perror("ftruncate");
        exit(EXIT_FAILURE);
    }
    return 0;
}

void * MappingSharedMemoryObjects(int fd , size_t mem_size,  std::string shared_mem_name)
{
    // 映射共享内存对象
    void *ptr = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (ptr == MAP_FAILED) {
        perror("mmap");
        shm_unlink(shared_mem_name.c_str());
        exit(EXIT_FAILURE);
    }
    return ptr;
}

int UnmappingSharedMemoryObjects(void *ptr , size_t mem_size,  std::string shared_mem_name)
{
    // 解除映射共享内存对象
    if (munmap(ptr, mem_size) == -1) {
        perror("munmap");
        shm_unlink(shared_mem_name.c_str());
        exit(EXIT_FAILURE);
    }
    return 0;
}

int CloseSharedMemoryObject(int fd , size_t mem_size,  std::string shared_mem_name)
{
    // 关闭共享内存对象
    if (close(fd) == -1) {
        perror("close");
        shm_unlink(shared_mem_name.c_str());
        exit(EXIT_FAILURE);
    }
    return 0;
}

int DeleteSharedMemoryObject(int fd , size_t mem_size,  std::string shared_mem_name)
{
    // 删除共享内存对象
    if (shm_unlink(shared_mem_name.c_str()) == -1) {
        perror("shm_unlink");
        exit(EXIT_FAILURE);
    }
    return 0;
}

int main(int argc, char** argv)
{
    std::string mem_name{"/MY_SHM"};
    size_t mem_size = sysconf(_SC_PAGE_SIZE) * 2;

    std::cout << "mem_Size = " << mem_size << std::endl;

    int fd;
     // 创建并打开共享内存对象
    CreateSharedMemory(&fd,mem_name);
    // 设置共享内存对象的大小
    SetSharedMemoryObjectSize(fd, mem_size, mem_name);
    // 映射共享内存对象
    void *ptr = MappingSharedMemoryObjects(fd, mem_size, mem_name);
    

    // 使用共享内存对象
    // 例如，将字符串写入共享内存
    sprintf(static_cast<char *> (ptr), "Hello, Shared Memory!");
    std::cout << "Read from shared memory: "<< std::string((char *)ptr) << std::endl;

    // 解除映射共享内存对象
    UnmappingSharedMemoryObjects(ptr, mem_size, mem_name);

    // 关闭共享内存对象
    CloseSharedMemoryObject(fd, mem_size, mem_name);

    // 删除共享内存对象
    DeleteSharedMemoryObject(fd, mem_size, mem_name);

    printf("Shared memory object closed and unlinked successfully.\n");

    return 0;
}